package model

import (
	"common/helper"
	"database/sql"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	g "github.com/doug-martin/goqu/v9"
	"github.com/doug-martin/goqu/v9/exp"
)

type WhiteListData struct {
	D []TblWhitelist `json:"d"`
	T int            `json:"total"`
	S int            `json:"s"`
}

// 白名单
// 白名单配置表
type TblWhitelist struct {
	Id          string `db:"id" json:"id"`
	Ip          string `db:"ip" json:"ip"`                     //ip
	Remark      string `db:"remark" json:"remark"`             //备注
	CreatedAt   uint32 `db:"created_at" json:"created_at"`     //添加时间
	CreatedUid  string `db:"created_uid" json:"created_uid"`   //添加人uid
	CreatedName string `db:"created_name" json:"created_name"` //添加人名
	Area        string `db:"area" json:"area"`                 //区域 国家 省 市
}

const whiteListkey = "ht:whitelist"

func WhiteListInsert(adminID, adminName, ip, remark string) error {

	country, region, city, err := IpLocation(ip)
	if err != nil {
		return err
	}

	data := TblWhitelist{
		Id:          helper.GenId(),
		Ip:          ip,
		Area:        country + " " + region + " " + city,
		Remark:      remark,
		CreatedAt:   uint32(time.Now().Unix()),
		CreatedUid:  adminID,
		CreatedName: adminName,
	}
	query, _, _ := dialect.Insert("tbl_whitelist").Rows(data).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		if strings.HasPrefix(err.Error(), "Error 1062") {
			return errors.New(helper.RecordExistErr)
		}

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	err = meta.MerchantRedis.SAdd(ctx, whiteListkey, ip).Err()
	return err
}

func WhiteListList(startTime, endTime string, ex g.Ex, page, pageSize int) (WhiteListData, error) {

	data := WhiteListData{}
	if startTime != "" && endTime != "" {
		startAt, err := time.ParseInLocation("2006-01-02 15:04:05", startTime, time.Local)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		endAt, err := time.ParseInLocation("2006-01-02 15:04:05", endTime, time.Local)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		if startAt.Unix() >= endAt.Unix() {
			return data, errors.New(helper.QueryTimeRangeErr)
		}
		ex["created_at"] = g.Op{"between": exp.NewRangeVal(startAt.Unix(), endAt.Unix())}
	}

	t := dialect.From("tbl_whitelist")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}

	offset := (page - 1) * pageSize
	query, _, _ := t.Select(colsWhiteList...).Where(ex).Order(g.C("created_at").Desc()).Offset(uint(offset)).Limit(uint(pageSize)).ToSQL()

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	data.S = pageSize

	return data, nil
}

func WhiteListDelete(adminName, id string) error {

	data := TblWhitelist{}
	ex := g.Ex{
		"id": id,
	}
	query, _, _ := dialect.From("tbl_whitelist").Select(colsWhiteList...).Where(ex).ToSQL()
	err := meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return errors.New(helper.RecordNotExistErr)
	}

	query, _, _ = dialect.Delete("tbl_whitelist").Where(ex).ToSQL()

	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	err = meta.MerchantRedis.SRem(ctx, whiteListkey, data.Ip).Err()

	return err
}

func GetAdminWhiteListMap() []string {
	data := []string{}
	query := "select ip from tbl_admin_whitelist"
	meta.MerchantDB.Select(&data, query)
	return data
}
func WhiteListCheck(ip string) bool {
	list := GetAdminWhiteListMap()
	for _, value := range list {
		if value == ip {
			return true
		}
	}
	return false
}

type TblAdminWhitelist struct {
	Ip         string `db:"ip" json:"ip"`                   //ip
	Status     string `db:"status" json:"status"`           //备注
	Remark     string `db:"remark" json:"remark"`           //备注
	CreateAt   uint32 `db:"create_at" json:"create_at"`     //添加时间
	CreateUid  string `db:"create_uid" json:"create_uid"`   //添加人uid
	CreateName string `db:"create_name" json:"create_name"` //添加人名
	UpdateAt   uint32 `db:"update_at" json:"update_at"`     //添加时间
	UpdateUid  string `db:"update_uid" json:"update_uid"`   //
	UpdateUame string `db:"update_name" json:"update_name"` //
	MerchantId string `db:"merchant_id" json:"merchant_id"` //
}

func WhiteListLimit(ip string) {
	client := meta.MerchantRedis
	rediskey := "登陆限制：" + ip
	has := client.Get(ctx, rediskey).Val()

	if has == "" {
		//60秒过期
		client.Set(ctx, rediskey, 1, 60*time.Second)
	} else {
		client.Incr(ctx, rediskey)
		errnumint, _ := strconv.Atoi(has)
		if (errnumint + 1) >= 50 {
			data := TblAdminWhitelist{
				Ip:         ip,
				Status:     "1",
				Remark:     "limit",
				CreateAt:   uint32(time.Now().Unix()),
				CreateUid:  "0",
				CreateName: "admin",
				UpdateAt:   uint32(time.Now().Unix()),
				UpdateUid:  "0",
				UpdateUame: "admin",
				MerchantId: "0",
			}
			query, _, _ := dialect.Insert("tbl_admin_whitelist").Rows(data).ToSQL()
			meta.MerchantDB.Exec(query)
		}
	}
}
